home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / aspisrc.zip / RTAPE_LI.C < prev    next >
C/C++ Source or Header  |  1992-01-26  |  14KB  |  650 lines

  1. /* Remote tape emulator subroutines.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* JF: modified to make all rmtXXX calls into macros for speed */
  21.  
  22. #ifndef lint
  23. static char *RCSid = "$Header: /usr/src/local/usr.lib/librmt/RCS/rmtlib.c,v 1.7 89/03/23 14:09:51 root Exp Locker: root $";
  24. #endif
  25.  
  26. /*
  27.  * $Log:    rmtlib.c,v $
  28.  * Revision 1.7  89/03/23  14:09:51  root
  29.  * Fix from haynes@ucscc.ucsc.edu for use w/compat. ADR.
  30.  * 
  31.  * Revision 1.6  88/10/25  17:04:29  root
  32.  * rexec code and a bug fix from srs!dan, miscellanious cleanup. ADR.
  33.  * 
  34.  * Revision 1.5  88/10/25  16:30:17  root
  35.  * Fix from jeff@gatech.edu for getting user@host:dev right. ADR.
  36.  * 
  37.  * Revision 1.4  87/10/30  10:36:12  root
  38.  * Made 4.2 syntax a compile time option. ADR.
  39.  * 
  40.  * Revision 1.3  87/04/22  11:16:48  root
  41.  * Two fixes from parmelee@wayback.cs.cornell.edu to correctly
  42.  * do fd biasing and rmt protocol on 'S' command. ADR.
  43.  * 
  44.  * Revision 1.2  86/10/09  16:38:53  root
  45.  * Changed to reflect 4.3BSD rcp syntax. ADR.
  46.  * 
  47.  * Revision 1.1  86/10/09  16:17:35  root
  48.  * Initial revision
  49.  * 
  50.  */
  51.  
  52. /*
  53.  *    rmt --- remote tape emulator subroutines
  54.  *
  55.  *    Originally written by Jeff Lee, modified some by Arnold Robbins
  56.  *
  57.  *    WARNING:  The man page rmt(8) for /etc/rmt documents the remote mag
  58.  *    tape protocol which rdump and rrestore use.  Unfortunately, the man
  59.  *    page is *WRONG*.  The author of the routines I'm including originally
  60.  *    wrote his code just based on the man page, and it didn't work, so he
  61.  *    went to the rdump source to figure out why.  The only thing he had to
  62.  *    change was to check for the 'F' return code in addition to the 'E',
  63.  *    and to separate the various arguments with \n instead of a space.  I
  64.  *    personally don't think that this is much of a problem, but I wanted to
  65.  *    point it out.
  66.  *    -- Arnold Robbins
  67.  *
  68.  *    Redone as a library that can replace open, read, write, etc, by
  69.  *    Fred Fish, with some additional work by Arnold Robbins.
  70.  */
  71.  
  72. /* Use -DUSE_REXEC for rexec code, courtesy of Dan Kegel, srs!dan */
  73.  
  74. #if defined(USG) && !defined(HAVE_MTIO)
  75. #define NO_RMTIOCTL
  76. #endif
  77.  
  78. #include <stdio.h>
  79. #include <signal.h>
  80. #include <sys/types.h>
  81.  
  82. #ifndef NO_RMTIOCTL
  83. #include <sys/ioctl.h>
  84. #include <sys/mtio.h>
  85. #endif
  86.  
  87. #ifdef USE_REXEC
  88. #include <netdb.h>
  89. #endif
  90.  
  91. #include <errno.h>
  92. #include <setjmp.h>
  93. #include <sys/stat.h>
  94.  
  95. #define BUFMAGIC    64    /* a magic number for buffer sizes */
  96.  
  97. /*
  98.  *    MAXUNIT --- Maximum number of remote tape file units
  99.  */
  100. #define MAXUNIT    4
  101.  
  102. /*
  103.  *    READ --- Return the number of the read side file descriptor
  104.  *    WRITE --- Return the number of the write side file descriptor
  105.  */
  106. #define READ(fd)    (Ctp[fd][0])
  107. #define WRITE(fd)    (Ptc[fd][1])
  108.  
  109. static int Ctp[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  110. static int Ptc[MAXUNIT][2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
  111.  
  112. extern int errno;
  113.  
  114. char *__rmt_path;
  115.  
  116. /*
  117.  *    _rmt_panic --- close off a remote tape connection
  118.  */
  119.  
  120. static void _rmt_panic(fildes)
  121. int fildes;
  122. {
  123.     close(READ(fildes));
  124.     close(WRITE(fildes));
  125.     READ(fildes) = -1;
  126.     WRITE(fildes) = -1;
  127. }
  128.  
  129.  
  130.  
  131. /*
  132.  *    command --- attempt to perform a remote tape command
  133.  */
  134.  
  135. static int command(fildes, buf)
  136. int fildes;
  137. char *buf;
  138. {
  139.     register int blen;
  140. #ifdef SIGNAL_VOID
  141.     void (*pstat)();
  142. #else
  143.     int (*pstat)();
  144. #endif
  145.  
  146. /*
  147.  *    save current pipe status and try to make the request
  148.  */
  149.  
  150.     blen = strlen(buf);
  151.     pstat = signal(SIGPIPE, SIG_IGN);
  152.     if (write(WRITE(fildes), buf, blen) == blen)
  153.     {
  154.         signal(SIGPIPE, pstat);
  155.         return(0);
  156.     }
  157.  
  158. /*
  159.  *    something went wrong. close down and go home
  160.  */
  161.  
  162.     signal(SIGPIPE, pstat);
  163.     _rmt_panic(fildes);
  164.  
  165.     errno = EIO;
  166.     return(-1);
  167. }
  168.  
  169.  
  170.  
  171. /*
  172.  *    status --- retrieve the status from the pipe
  173.  */
  174.  
  175. static int status(fildes)
  176. int fildes;
  177. {
  178.     int i;
  179.     char c, *cp;
  180.     char buffer[BUFMAGIC];
  181.  
  182. /*
  183.  *    read the reply command line
  184.  */
  185.  
  186.     for (i = 0, cp = buffer; i < BUFMAGIC; i++, cp++)
  187.     {
  188.         if (read(READ(fildes), cp, 1) != 1)
  189.         {
  190.             _rmt_panic(fildes);
  191.             errno = EIO;
  192.             return(-1);
  193.         }
  194.         if (*cp == '\n')
  195.         {
  196.             *cp = 0;
  197.             break;
  198.         }
  199.     }
  200.  
  201.     if (i == BUFMAGIC)
  202.     {
  203.         _rmt_panic(fildes);
  204.         errno = EIO;
  205.         return(-1);
  206.     }
  207.  
  208. /*
  209.  *    check the return status
  210.  */
  211.  
  212.     for (cp = buffer; *cp; cp++)
  213.         if (*cp != ' ')
  214.             break;
  215.  
  216.     if (*cp == 'E' || *cp == 'F')
  217.     {
  218.         errno = atoi(cp + 1);
  219.         while (read(READ(fildes), &c, 1) == 1)
  220.             if (c == '\n')
  221.                 break;
  222.  
  223.         if (*cp == 'F')
  224.             _rmt_panic(fildes);
  225.  
  226.         return(-1);
  227.     }
  228.  
  229. /*
  230.  *    check for mis-synced pipes
  231.  */
  232.  
  233.     if (*cp != 'A')
  234.     {
  235.         _rmt_panic(fildes);
  236.         errno = EIO;
  237.         return(-1);
  238.     }
  239.  
  240.     return(atoi(cp + 1));
  241. }
  242.  
  243. #ifdef USE_REXEC
  244.  
  245. /*
  246.  * _rmt_rexec
  247.  *
  248.  * execute /etc/rmt on a remote system using rexec().
  249.  * Return file descriptor of bidirectional socket for stdin and stdout
  250.  * If username is NULL, or an empty string, uses current username.
  251.  *
  252.  * ADR: By default, this code is not used, since it requires that
  253.  * the user have a .netrc file in his/her home directory, or that the
  254.  * application designer be willing to have rexec prompt for login and
  255.  * password info. This may be unacceptable, and .rhosts files for use
  256.  * with rsh are much more common on BSD systems.
  257.  */
  258.  
  259. static int
  260. _rmt_rexec(host, user)
  261. char *host;
  262. char *user;        /* may be NULL */
  263. {
  264.     struct servent *rexecserv;
  265.     int save_stdin = dup(fileno(stdin));
  266.     int save_stdout = dup(fileno(stdout));
  267.     int tape_fd;        /* Return value. */
  268.  
  269.     /*
  270.      * When using cpio -o < filename, stdin is no longer the tty.
  271.      * But the rexec subroutine reads the login and the passwd on stdin, 
  272.      * to allow remote execution of the command.
  273.      * So, reopen stdin and stdout on /dev/tty before the rexec and
  274.      * give them back their original value after.
  275.      */
  276.     if (freopen("/dev/tty", "r", stdin) == NULL)
  277.         freopen("/dev/null", "r", stdin);
  278.     if (freopen("/dev/tty", "w", stdout) == NULL)
  279.         freopen("/dev/null", "w", stdout);
  280.  
  281.     rexecserv = getservbyname("exec", "tcp");
  282.     if (NULL == rexecserv) {
  283.         fprintf (stderr, "? exec/tcp: service not available.");
  284.         exit (-1);
  285.     }
  286.     if ((user != NULL) && *user == '\0')
  287.         user = (char *) NULL;
  288.     tape_fd = rexec (&host, rexecserv->s_port, user, NULL,
  289.              "/etc/rmt", (int *)NULL);
  290.     fclose(stdin);
  291.     fdopen(save_stdin, "r");
  292.     fclose(stdout);
  293.     fdopen(save_stdout, "w");
  294.  
  295.     return tape_fd;
  296. }
  297. #endif /* USE_REXEC */
  298.  
  299. /*
  300.  *    _rmt_open --- open a magtape device on system specified, as given user
  301.  *
  302.  *    file name has the form [user@]system:/dev/????
  303. #ifdef COMPAT
  304.  *    file name has the form system[.user]:/dev/????
  305. #endif
  306.  */
  307.  
  308. #define MAXHOSTLEN    257    /* BSD allows very long host names... */
  309.  
  310. int __rmt_open (path, oflag, mode, bias)
  311. char *path;
  312. int oflag;
  313. int mode;
  314. int bias;
  315. {
  316.     int i, rc;
  317.     char buffer[BUFMAGIC];
  318.     char system[MAXHOSTLEN];
  319.     char device[BUFMAGIC];
  320.     char login[BUFMAGIC];
  321.     char *sys, *dev, *user;
  322.  
  323.     sys = system;
  324.     dev = device;
  325.     user = login;
  326.  
  327. /*
  328.  *    first, find an open pair of file descriptors
  329.  */
  330.  
  331.     for (i = 0; i < MAXUNIT; i++)
  332.         if (READ(i) == -1 && WRITE(i) == -1)
  333.             break;
  334.  
  335.     if (i == MAXUNIT)
  336.     {
  337.         errno = EMFILE;
  338.         return(-1);
  339.     }
  340.  
  341. /*
  342.  *    pull apart system and device, and optional user
  343.  *    don't munge original string
  344.  *    if COMPAT is defined, also handle old (4.2) style person.site notation.
  345.  */
  346.  
  347.     while (*path != '@'
  348. #ifdef COMPAT
  349.             && *path != '.'
  350. #endif
  351.             && *path != ':') {
  352.         *sys++ = *path++;
  353.     }
  354.     *sys =